Refactor testing the registry
authorAlex Crichton <alex@alexcrichton.com>
Wed, 11 Nov 2015 02:08:06 +0000 (18:08 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 11 Nov 2015 02:10:06 +0000 (18:10 -0800)
Use a builder to publish packages instead of a one-off function with many
variants, should provide a much finer grained level of configurability for
future test cases against the registry.

tests/support/registry.rs
tests/test_cargo_install.rs
tests/test_cargo_package.rs
tests/test_cargo_registry.rs

index be48cb7845ec94d89ce4947d334a23a8b59b6e9a..df0d5301a91327632c9f1e775392234e328ce540 100644 (file)
@@ -6,10 +6,9 @@ use flate2::Compression::Default;
 use flate2::write::GzEncoder;
 use git2;
 use rustc_serialize::hex::ToHex;
-use tar::Archive;
+use tar::{Archive, Header};
 use url::Url;
 
-use support::project;
 use support::paths;
 use support::git::repo;
 use cargo::util::Sha256;
@@ -19,9 +18,20 @@ pub fn registry() -> Url { Url::from_file_path(&*registry_path()).ok().unwrap()
 pub fn dl_path() -> PathBuf { paths::root().join("dl") }
 pub fn dl_url() -> Url { Url::from_file_path(&*dl_path()).ok().unwrap() }
 
-pub fn init() {
+pub struct Package {
+    name: String,
+    vers: String,
+    deps: Vec<(String, String, &'static str)>,
+    files: Vec<(String, String)>,
+    yanked: bool,
+}
+
+fn init() {
     let config = paths::home().join(".cargo/config");
     fs::create_dir_all(config.parent().unwrap()).unwrap();
+    if fs::metadata(&config).is_ok() {
+        return
+    }
     File::create(&config).unwrap().write_all(format!(r#"
         [registry]
             index = "{reg}"
@@ -36,114 +46,142 @@ pub fn init() {
         .build();
 }
 
-pub fn mock_archive(name: &str, version: &str, deps: &[(&str, &str, &str)]) {
-    let mut manifest = format!(r#"
-        [package]
-        name = "{}"
-        version = "{}"
-        authors = []
-    "#, name, version);
-    for &(dep, req, kind) in deps.iter() {
-        manifest.push_str(&format!(r#"
-            [{}dependencies.{}]
-            version = "{}"
-        "#, match kind {
-            "build" => "build-",
-            "dev" => "dev-",
-            _ => ""
-        }, dep, req));
+impl Package {
+    pub fn new(name: &str, vers: &str) -> Package {
+        init();
+        Package {
+            name: name.to_string(),
+            vers: vers.to_string(),
+            deps: Vec::new(),
+            files: Vec::new(),
+            yanked: false,
+        }
     }
-    let p = project(name)
-        .file("Cargo.toml", &manifest)
-        .file("src/lib.rs", "")
-        .file("src/main.rs", &format!("\
-            extern crate {};
-            fn main() {{}}
-        ", name));
-    p.build();
-
-    let dst = mock_archive_dst(name, version);
-    fs::create_dir_all(dst.parent().unwrap()).unwrap();
-    let f = File::create(&dst).unwrap();
-    let a = Archive::new(GzEncoder::new(f, Default));
-    a.append_file(&format!("{}-{}/Cargo.toml", name, version),
-                  &mut File::open(&p.root().join("Cargo.toml")).unwrap()).unwrap();
-    a.append_file(&format!("{}-{}/src/lib.rs", name, version),
-                  &mut File::open(&p.root().join("src/lib.rs")).unwrap()).unwrap();
-    a.append_file(&format!("{}-{}/src/main.rs", name, version),
-                  &mut File::open(&p.root().join("src/main.rs")).unwrap()).unwrap();
-    a.finish().unwrap();
-}
 
-pub fn mock_archive_dst(name: &str, version: &str) -> PathBuf {
-    dl_path().join(name).join(version).join("download")
-}
+    pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
+        self.files.push((name.to_string(), contents.to_string()));
+        self
+    }
 
-pub fn mock_pkg(name: &str, version: &str, deps: &[(&str, &str, &str)]) {
-    mock_pkg_yank(name, version, deps, false)
-}
+    pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {
+        self.deps.push((name.to_string(), vers.to_string(), "normal"));
+        self
+    }
 
-pub fn mock_pkg_yank(name: &str, version: &str, deps: &[(&str, &str, &str)],
-                     yanked: bool) {
-    mock_archive(name, version, deps);
-    let mut c = Vec::new();
-    File::open(&mock_archive_dst(name, version)).unwrap()
-         .read_to_end(&mut c).unwrap();
-    let line = pkg(name, version, deps, &cksum(&c), yanked);
-
-    let file = match name.len() {
-        1 => format!("1/{}", name),
-        2 => format!("2/{}", name),
-        3 => format!("3/{}/{}", &name[..1], name),
-        _ => format!("{}/{}/{}", &name[0..2], &name[2..4], name),
-    };
-    publish(&file, &line);
-}
+    pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {
+        self.deps.push((name.to_string(), vers.to_string(), "dev"));
+        self
+    }
+
+    pub fn yanked(&mut self, yanked: bool) -> &mut Package {
+        self.yanked = yanked;
+        self
+    }
+
+    #[allow(deprecated)] // connect => join in 1.3
+    pub fn publish(&self) {
+        self.make_archive();
 
-pub fn publish(file: &str, line: &str) {
-    let repo = git2::Repository::open(&registry_path()).unwrap();
-    let mut index = repo.index().unwrap();
-    {
-        let dst = registry_path().join(file);
+        // Figure out what we're going to write into the index
+        let deps = self.deps.iter().map(|&(ref name, ref req, ref kind)| {
+            format!("{{\"name\":\"{}\",\
+                       \"req\":\"{}\",\
+                       \"features\":[],\
+                       \"default_features\":false,\
+                       \"target\":null,\
+                       \"optional\":false,\
+                       \"kind\":\"{}\"}}", name, req, kind)
+        }).collect::<Vec<_>>().connect(",");
+        let cksum = {
+            let mut c = Vec::new();
+            File::open(&self.archive_dst()).unwrap()
+                 .read_to_end(&mut c).unwrap();
+            cksum(&c)
+        };
+        let line = format!("{{\"name\":\"{}\",\"vers\":\"{}\",\
+                              \"deps\":[{}],\"cksum\":\"{}\",\"features\":{{}},\
+                              \"yanked\":{}}}",
+                         self.name, self.vers, deps, cksum, self.yanked);
+        let file = match self.name.len() {
+            1 => format!("1/{}", self.name),
+            2 => format!("2/{}", self.name),
+            3 => format!("3/{}/{}", &self.name[..1], self.name),
+            _ => format!("{}/{}/{}", &self.name[0..2], &self.name[2..4], self.name),
+        };
+
+        // Write file/line in the index
+        let dst = registry_path().join(&file);
         let mut prev = String::new();
         let _ = File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev));
         fs::create_dir_all(dst.parent().unwrap()).unwrap();
         File::create(&dst).unwrap()
-            .write_all((prev + line + "\n").as_bytes()).unwrap();
+             .write_all((prev + &line[..] + "\n").as_bytes()).unwrap();
+
+        // Add the new file to the index
+        let repo = git2::Repository::open(&registry_path()).unwrap();
+        let mut index = repo.index().unwrap();
+        index.add_path(Path::new(&file)).unwrap();
+        index.write().unwrap();
+        let id = index.write_tree().unwrap();
+
+        // Commit this change
+        let tree = repo.find_tree(id).unwrap();
+        let sig = repo.signature().unwrap();
+        let parent = repo.refname_to_id("refs/heads/master").unwrap();
+        let parent = repo.find_commit(parent).unwrap();
+        repo.commit(Some("HEAD"), &sig, &sig,
+                    "Another commit", &tree,
+                    &[&parent]).unwrap();
     }
-    index.add_path(Path::new(file)).unwrap();
-    index.write().unwrap();
-    let id = index.write_tree().unwrap();
-    let tree = repo.find_tree(id).unwrap();
-    let sig = repo.signature().unwrap();
-    let parent = repo.refname_to_id("refs/heads/master").unwrap();
-    let parent = repo.find_commit(parent).unwrap();
-    repo.commit(Some("HEAD"), &sig, &sig,
-                "Another commit", &tree,
-                &[&parent]).unwrap();
-}
 
-#[allow(deprecated)] // connect => join in 1.3
-pub fn pkg(name: &str, vers: &str, deps: &[(&str, &str, &str)], cksum: &str,
-           yanked: bool) -> String {
-    let deps = deps.iter().map(|&(a, b, c)| dep(a, b, c)).collect::<Vec<String>>();
-    format!("{{\"name\":\"{}\",\"vers\":\"{}\",\
-               \"deps\":[{}],\"cksum\":\"{}\",\"features\":{{}},\
-               \"yanked\":{}}}",
-            name, vers, deps.connect(","), cksum, yanked)
-}
+    fn make_archive(&self) {
+        let mut manifest = format!(r#"
+            [package]
+            name = "{}"
+            version = "{}"
+            authors = []
+        "#, self.name, self.vers);
+        for &(ref dep, ref req, kind) in self.deps.iter() {
+            manifest.push_str(&format!(r#"
+                [{}dependencies.{}]
+                version = "{}"
+            "#, match kind {
+                "build" => "build-",
+                "dev" => "dev-",
+                _ => ""
+            }, dep, req));
+        }
 
-pub fn dep(name: &str, req: &str, kind: &str) -> String {
-    format!("{{\"name\":\"{}\",\
-               \"req\":\"{}\",\
-               \"features\":[],\
-               \"default_features\":false,\
-               \"target\":null,\
-               \"optional\":false,\
-               \"kind\":\"{}\"}}", name, req, kind)
+        let dst = self.archive_dst();
+        fs::create_dir_all(dst.parent().unwrap()).unwrap();
+        let f = File::create(&dst).unwrap();
+        let a = Archive::new(GzEncoder::new(f, Default));
+        self.append(&a, "Cargo.toml", &manifest);
+        if self.files.len() == 0 {
+            self.append(&a, "src/lib.rs", "");
+        } else {
+            for &(ref name, ref contents) in self.files.iter() {
+                self.append(&a, name, contents);
+            }
+        }
+        a.finish().unwrap();
+    }
+
+    fn append<W: Write>(&self, ar: &Archive<W>, file: &str, contents: &str) {
+        let mut header = Header::new();
+        header.set_size(contents.len() as u64);
+        header.set_path(format!("{}-{}/{}", self.name, self.vers, file)).unwrap();
+        header.set_cksum();
+
+        ar.append(&header, &mut contents.as_bytes()).unwrap();
+    }
+
+    pub fn archive_dst(&self) -> PathBuf {
+        dl_path().join(&self.name).join(&self.vers).join("download")
+    }
 }
 
-pub fn cksum(s: &[u8]) -> String {
+fn cksum(s: &[u8]) -> String {
     let mut sha = Sha256::new();
     sha.update(s);
     sha.finish().to_hex()
index a26c75997ffe8aa52a946e6fc7b6169f07be1fea..cd1e926ab15528bb0efdd34fb4d74d4b492c4f68 100644 (file)
@@ -9,13 +9,22 @@ use hamcrest::{assert_that, existing_file, is_not, Matcher, MatchResult};
 use support::{project, execs, cargo_dir};
 use support::{UPDATING, DOWNLOADING, COMPILING, INSTALLING, REMOVING};
 use support::paths;
-use support::registry as r;
+use support::registry::Package;
 use support::git;
 
 use self::InstalledExe as has_installed_exe;
 
 fn setup() {
-    r::init();
+}
+
+fn pkg(name: &str, vers: &str) {
+    Package::new(name, vers)
+        .file("src/lib.rs", "")
+        .file("src/main.rs", &format!("
+            extern crate {};
+            fn main() {{}}
+        ", name))
+        .publish()
 }
 
 fn cargo_process(s: &str) -> ProcessBuilder {
@@ -50,7 +59,7 @@ impl fmt::Display for InstalledExe {
 }
 
 test!(simple {
-    r::mock_pkg("foo", "0.0.1", &[]);
+    pkg("foo", "0.0.1");
 
     assert_that(cargo_process("install").arg("foo"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -76,8 +85,8 @@ test!(simple {
 });
 
 test!(pick_max_version {
-    r::mock_pkg("foo", "0.0.1", &[]);
-    r::mock_pkg("foo", "0.0.2", &[]);
+    pkg("foo", "0.0.1");
+    pkg("foo", "0.0.2");
 
     assert_that(cargo_process("install").arg("foo"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -95,7 +104,7 @@ test!(pick_max_version {
 });
 
 test!(missing {
-    r::mock_pkg("foo", "0.0.1", &[]);
+    pkg("foo", "0.0.1");
     assert_that(cargo_process("install").arg("bar"),
                 execs().with_status(101).with_stderr("\
 could not find `bar` in `registry file://[..]`
@@ -103,7 +112,7 @@ could not find `bar` in `registry file://[..]`
 });
 
 test!(bad_version {
-    r::mock_pkg("foo", "0.0.1", &[]);
+    pkg("foo", "0.0.1");
     assert_that(cargo_process("install").arg("foo").arg("--vers=0.2.0"),
                 execs().with_status(101).with_stderr("\
 could not find `foo` in `registry file://[..]` with version `0.2.0`
@@ -118,7 +127,7 @@ must specify a crate to install from crates.io
 });
 
 test!(install_location_precedence {
-    r::mock_pkg("foo", "0.0.1", &[]);
+    pkg("foo", "0.0.1");
 
     let root = paths::root();
     let t1 = root.join("t1");
@@ -428,9 +437,9 @@ test!(git_repo {
 });
 
 test!(list {
-    r::mock_pkg("foo", "0.0.1", &[]);
-    r::mock_pkg("bar", "0.2.1", &[]);
-    r::mock_pkg("bar", "0.2.2", &[]);
+    pkg("foo", "0.0.1");
+    pkg("bar", "0.2.1");
+    pkg("bar", "0.2.2");
 
     assert_that(cargo_process("install").arg("--list"),
                 execs().with_status(0).with_stdout(""));
@@ -456,7 +465,7 @@ package id specification `foo` matched no packages
 });
 
 test!(uninstall_bin_does_not_exist {
-    r::mock_pkg("foo", "0.0.1", &[]);
+    pkg("foo", "0.0.1");
 
     assert_that(cargo_process("install").arg("foo"),
                 execs().with_status(0));
index 5088d1ce2ec10bd2071bbada3cf7ade698b9965c..3c8a7a5837f3ad84c53ddd8e52ec4e6a2f780647 100644 (file)
@@ -10,7 +10,7 @@ use tar::Archive;
 
 use support::{project, execs, cargo_dir, paths, git, path2url};
 use support::{PACKAGING, VERIFYING, COMPILING, ARCHIVING, UPDATING, DOWNLOADING};
-use support::registry as r;
+use support::registry::{self, Package};
 use hamcrest::{assert_that, existing_file};
 
 fn setup() {
@@ -143,8 +143,6 @@ http://doc.crates.io/manifest.html#package-metadata for more info."));
 });
 
 test!(wildcard_deps {
-    r::init();
-
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
@@ -166,9 +164,9 @@ test!(wildcard_deps {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "0.0.1", "normal")]);
-    r::mock_pkg("buz", "0.0.1", &[("bar", "0.0.1", "normal")]);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("bar", "0.0.1").dep("baz", "0.0.1").publish();
+    Package::new("buz", "0.0.1").dep("bar", "0.0.1").publish();
 
     assert_that(p.cargo_process("package"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -188,7 +186,7 @@ test!(wildcard_deps {
         downloading = DOWNLOADING,
         compiling = COMPILING,
         dir = p.url(),
-        reg = r::registry()))
+        reg = registry::registry()))
                 .with_stderr("\
 warning: some dependencies have wildcard (\"*\") version constraints. On December 11th, 2015, \
 crates.io will begin rejecting packages with wildcard dependency constraints. See \
index 8209b5bb2935266adcadba2368953ea9e683fcb7..3f9fd85115a289c7140037b78418f1dd5967c60f 100644 (file)
@@ -5,13 +5,12 @@ use cargo::util::process;
 use support::{project, execs, cargo_dir};
 use support::{UPDATING, DOWNLOADING, COMPILING, PACKAGING, VERIFYING, ADDING, REMOVING};
 use support::paths::{self, CargoPathExt};
-use support::registry as r;
+use support::registry::{self, Package};
 use support::git;
 
 use hamcrest::assert_that;
 
 fn setup() {
-    r::init();
 }
 
 test!(simple {
@@ -27,7 +26,7 @@ test!(simple {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
 
     assert_that(p.cargo_process("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -40,7 +39,7 @@ test!(simple {
         downloading = DOWNLOADING,
         compiling = COMPILING,
         dir = p.url(),
-        reg = r::registry())));
+        reg = registry::registry())));
 
     // Don't download a second time
     assert_that(p.cargo_process("build"),
@@ -51,7 +50,7 @@ test!(simple {
 ",
         updating = UPDATING,
         dir = p.url(),
-        reg = r::registry())));
+        reg = registry::registry())));
 });
 
 test!(deps {
@@ -67,8 +66,8 @@ test!(deps {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "*", "normal")]);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("bar", "0.0.1").dep("baz", "*").publish();
 
     assert_that(p.cargo_process("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -83,10 +82,12 @@ test!(deps {
         downloading = DOWNLOADING,
         compiling = COMPILING,
         dir = p.url(),
-        reg = r::registry())));
+        reg = registry::registry())));
 });
 
 test!(nonexistent {
+    Package::new("init", "0.0.1").publish();
+
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
@@ -120,8 +121,8 @@ test!(wrong_version {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    r::mock_pkg("foo", "0.0.1", &[]);
-    r::mock_pkg("foo", "0.0.2", &[]);
+    Package::new("foo", "0.0.1").publish();
+    Package::new("foo", "0.0.2").publish();
 
     assert_that(p.cargo_process("build"),
                 execs().with_status(101).with_stderr("\
@@ -131,8 +132,8 @@ version required: >= 1.0.0
 versions found: 0.0.2, 0.0.1
 "));
 
-    r::mock_pkg("foo", "0.0.3", &[]);
-    r::mock_pkg("foo", "0.0.4", &[]);
+    Package::new("foo", "0.0.3").publish();
+    Package::new("foo", "0.0.4").publish();
 
     assert_that(p.cargo_process("build"),
                 execs().with_status(101).with_stderr("\
@@ -156,8 +157,9 @@ test!(bad_cksum {
         "#)
         .file("src/main.rs", "fn main() {}");
 
-    r::mock_pkg("bad-cksum", "0.0.1", &[]);
-    File::create(&r::mock_archive_dst("bad-cksum", "0.0.1")).unwrap();
+    let pkg = Package::new("bad-cksum", "0.0.1");
+    pkg.publish();
+    File::create(&pkg.archive_dst()).unwrap();
 
     assert_that(p.cargo_process("build").arg("-v"),
                 execs().with_status(101).with_stderr("\
@@ -172,6 +174,8 @@ Caused by:
 });
 
 test!(update_registry {
+    Package::new("init", "0.0.1").publish();
+
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
@@ -191,7 +195,7 @@ location searched: registry file://[..]
 version required: >= 0.0.0
 "));
 
-    r::mock_pkg("notyet", "0.0.1", &[]);
+    Package::new("notyet", "0.0.1").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -204,10 +208,12 @@ version required: >= 0.0.0
         downloading = DOWNLOADING,
         compiling = COMPILING,
         dir = p.url(),
-        reg = r::registry())));
+        reg = registry::registry())));
 });
 
 test!(package_with_path_deps {
+    Package::new("init", "0.0.1").publish();
+
     let p = project("foo")
         .file("Cargo.toml", r#"
             [project]
@@ -242,7 +248,7 @@ location searched: registry file://[..]
 version required: ^0.0.1
 "));
 
-    r::mock_pkg("notyet", "0.0.1", &[]);
+    Package::new("notyet", "0.0.1").publish();
 
     assert_that(p.cargo("package"),
                 execs().with_status(0).with_stdout(format!("\
@@ -276,7 +282,7 @@ test!(lockfile_locks {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -288,7 +294,7 @@ test!(lockfile_locks {
    dir = p.url())));
 
     p.root().move_into_the_past().unwrap();
-    r::mock_pkg("bar", "0.0.2", &[]);
+    Package::new("bar", "0.0.2").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(""));
@@ -308,8 +314,8 @@ test!(lockfile_locks_transitively {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "*", "normal")]);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("bar", "0.0.1").dep("baz", "*").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -323,8 +329,8 @@ test!(lockfile_locks_transitively {
    dir = p.url())));
 
     p.root().move_into_the_past().unwrap();
-    r::mock_pkg("baz", "0.0.2", &[]);
-    r::mock_pkg("bar", "0.0.2", &[("baz", "*", "normal")]);
+    Package::new("baz", "0.0.2").publish();
+    Package::new("bar", "0.0.2").dep("baz", "*").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(""));
@@ -344,10 +350,10 @@ test!(yanks_are_not_used {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg_yank("baz", "0.0.2", &[], true);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "*", "normal")]);
-    r::mock_pkg_yank("bar", "0.0.2", &[("baz", "*", "normal")], true);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("baz", "0.0.2").yanked(true).publish();
+    Package::new("bar", "0.0.1").dep("baz", "*").publish();
+    Package::new("bar", "0.0.2").dep("baz", "*").yanked(true).publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -375,9 +381,9 @@ test!(relying_on_a_yank_is_bad {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg_yank("baz", "0.0.2", &[], true);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "=0.0.2", "normal")]);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("baz", "0.0.2").yanked(true).publish();
+    Package::new("bar", "0.0.1").dep("baz", "=0.0.2").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr("\
@@ -402,14 +408,14 @@ test!(yanks_in_lockfiles_are_ok {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0));
 
-    fs::remove_dir_all(&r::registry_path().join("3")).unwrap();
+    fs::remove_dir_all(&registry::registry_path().join("3")).unwrap();
 
-    r::mock_pkg_yank("bar", "0.0.1", &[], true);
+    Package::new("bar", "0.0.1").yanked(true).publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(""));
@@ -436,7 +442,7 @@ test!(update_with_lockfile_if_packages_missing {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
     assert_that(p.cargo("build"),
                 execs().with_status(0));
     p.root().move_into_the_past().unwrap();
@@ -464,12 +470,12 @@ test!(update_lockfile {
     p.build();
 
     println!("0.0.1");
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
     assert_that(p.cargo("build"),
                 execs().with_status(0));
 
-    r::mock_pkg("bar", "0.0.2", &[]);
-    r::mock_pkg("bar", "0.0.3", &[]);
+    Package::new("bar", "0.0.2").publish();
+    Package::new("bar", "0.0.3").publish();
     paths::home().join(".cargo/registry").rm_rf().unwrap();
     println!("0.0.2 update");
     assert_that(p.cargo("update")
@@ -506,8 +512,8 @@ test!(update_lockfile {
    dir = p.url())));
 
    println!("new dependencies update");
-   r::mock_pkg("bar", "0.0.4", &[("spam", "0.2.5", "")]);
-   r::mock_pkg("spam", "0.2.5", &[]);
+   Package::new("bar", "0.0.4").dep("spam", "0.2.5").publish();
+   Package::new("spam", "0.2.5").publish();
    assert_that(p.cargo("update")
                 .arg("-p").arg("bar"),
                execs().with_status(0).with_stdout(&format!("\
@@ -517,7 +523,7 @@ test!(update_lockfile {
 ", updating = UPDATING, adding = ADDING)));
 
    println!("new dependencies update");
-   r::mock_pkg("bar", "0.0.5", &[]);
+   Package::new("bar", "0.0.5").publish();
    assert_that(p.cargo("update")
                 .arg("-p").arg("bar"),
                execs().with_status(0).with_stdout(&format!("\
@@ -541,8 +547,8 @@ test!(dev_dependency_not_used {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("baz", "0.0.1", &[]);
-    r::mock_pkg("bar", "0.0.1", &[("baz", "*", "dev")]);
+    Package::new("baz", "0.0.1").publish();
+    Package::new("bar", "0.0.1").dev_dep("baz", "*").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -608,7 +614,7 @@ test!(updating_a_dep {
         .file("a/src/lib.rs", "");
     p.build();
 
-    r::mock_pkg("bar", "0.0.1", &[]);
+    Package::new("bar", "0.0.1").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0).with_stdout(&format!("\
@@ -629,7 +635,7 @@ test!(updating_a_dep {
         [dependencies]
         bar = "0.1.0"
     "#).unwrap();
-    r::mock_pkg("bar", "0.1.0", &[]);
+    Package::new("bar", "0.1.0").publish();
 
     println!("second");
     assert_that(p.cargo("build"),
@@ -672,7 +678,7 @@ test!(git_and_registry_dep {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("a", "0.0.1", &[]);
+    Package::new("a", "0.0.1").publish();
 
     p.root().move_into_the_past().unwrap();
     assert_that(p.cargo("build"),
@@ -706,13 +712,12 @@ test!(update_publish_then_update {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("a", "0.1.0", &[]);
+    Package::new("a", "0.1.0").publish();
 
     assert_that(p.cargo("build"),
                 execs().with_status(0));
 
-
-    r::mock_pkg("a", "0.1.1", &[]);
+    Package::new("a", "0.1.1").publish();
 
     let lock = p.root().join("Cargo.lock");
     let mut s = String::new();
@@ -747,7 +752,7 @@ test!(fetch_downloads {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("a", "0.1.0", &[]);
+    Package::new("a", "0.1.0").publish();
 
     assert_that(p.cargo("fetch"),
                 execs().with_status(0)
@@ -771,13 +776,13 @@ test!(update_transitive_dependency {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("a", "0.1.0", &[("b", "*", "normal")]);
-    r::mock_pkg("b", "0.1.0", &[]);
+    Package::new("a", "0.1.0").dep("b", "*").publish();
+    Package::new("b", "0.1.0").publish();
 
     assert_that(p.cargo("fetch"),
                 execs().with_status(0));
 
-    r::mock_pkg("b", "0.1.1", &[]);
+    Package::new("b", "0.1.1").publish();
 
     assert_that(p.cargo("update").arg("-pb"),
                 execs().with_status(0)
@@ -810,18 +815,20 @@ test!(update_backtracking_ok {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("webdriver", "0.1.0", &[("hyper", "0.6", "normal")]);
-    r::mock_pkg("hyper", "0.6.5", &[("openssl", "0.1", "normal"),
-                                    ("cookie", "0.1", "normal")]);
-    r::mock_pkg("cookie", "0.1.0", &[("openssl", "0.1", "normal")]);
-    r::mock_pkg("openssl", "0.1.0", &[]);
+    Package::new("webdriver", "0.1.0").dep("hyper", "0.6").publish();
+    Package::new("hyper", "0.6.5").dep("openssl", "0.1")
+                                  .dep("cookie", "0.1")
+                                  .publish();
+    Package::new("cookie", "0.1.0").dep("openssl", "0.1").publish();
+    Package::new("openssl", "0.1.0").publish();
 
     assert_that(p.cargo("generate-lockfile"),
                 execs().with_status(0));
 
-    r::mock_pkg("openssl", "0.1.1", &[]);
-    r::mock_pkg("hyper", "0.6.6", &[("openssl", "0.1.1", "normal"),
-                                    ("cookie", "0.1.0", "normal")]);
+    Package::new("openssl", "0.1.1").publish();
+    Package::new("hyper", "0.6.6").dep("openssl", "0.1.1")
+                                  .dep("cookie", "0.1.0")
+                                  .publish();
 
     assert_that(p.cargo("update").arg("-p").arg("hyper"),
                 execs().with_status(0)
@@ -846,16 +853,16 @@ test!(update_multiple_packages {
         .file("src/main.rs", "fn main() {}");
     p.build();
 
-    r::mock_pkg("a", "0.1.0", &[]);
-    r::mock_pkg("b", "0.1.0", &[]);
-    r::mock_pkg("c", "0.1.0", &[]);
+    Package::new("a", "0.1.0").publish();
+    Package::new("b", "0.1.0").publish();
+    Package::new("c", "0.1.0").publish();
 
     assert_that(p.cargo("fetch"),
                 execs().with_status(0));
 
-    r::mock_pkg("a", "0.1.1", &[]);
-    r::mock_pkg("b", "0.1.1", &[]);
-    r::mock_pkg("c", "0.1.1", &[]);
+    Package::new("a", "0.1.1").publish();
+    Package::new("b", "0.1.1").publish();
+    Package::new("c", "0.1.1").publish();
 
     assert_that(p.cargo("update").arg("-pa").arg("-pb"),
                 execs().with_status(0)